package com.hmkj.web.controller;

import com.hmkj.common.baseMapper.GenericPo;
import com.hmkj.common.entity.ResultEntity;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.core.constant.CacheID;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.constant.PhoneCodeKey;
import com.hmkj.core.constant.SessionId;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.po.system.MessageTemplate;
import com.hmkj.core.po.user.User;
import com.hmkj.core.service.cache.RedisService;
import com.hmkj.core.service.cache.SessionService;
import com.hmkj.core.service.sms.SendMsgService;
import com.xiaoleilu.hutool.date.DateUnit;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.RandomUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * json数据类controller 基础实现
 *
 * @param <PK> 对象主键类型
 * @param <PO> 对象
 * @author Administrator
 */
@Slf4j
public class GenericController<PK, PO extends GenericPo<PK>> {

    /**
     * api地址跟路径
     */
    public static final String BASE_API_URL = "/api";
    /**
     * 用户需要登录的跟路径
     */
    public static final String MEMBER_URL = "/api/member";

    @Resource
    protected RedisService redisService;
    @Resource
    protected SessionService sessionService;
    @Resource
    protected SendMsgService sendMsgService;

    /**
     * 获取请求IP
     *
     * @param request
     * @return
     */
    public String getRequestIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

    /**
     * 获取请求域名
     *
     * @return
     */
    public String getDomain() {
        StringBuffer url = getRequest().getRequestURL();
        String tempContextUrl = url.delete(url.length() - getRequest().getRequestURI().length(), url.length()).toString();
        return tempContextUrl.replace("http://", "").replace("https://", "");
    }

    /**
     * 获取请求域名
     *
     * @return
     */
    public String getRequestUrl() {
        StringBuffer url = getRequest().getRequestURL();
        String tempContextUrl = url.delete(url.length() - getRequest().getRequestURI().length(), url.length()).toString();
        return tempContextUrl + "/";
    }

    /**
     * 获取缓存
     *
     * @param key
     * @return
     */
    protected String getSession(String key) {
        return getSession(key, String.class);
    }

    /**
     * 获取缓存
     *
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    protected <T> T getSession(String key, Class<T> clazz) {
        return sessionService.getSession(key, clazz, getRequest());
    }

    /**
     * 保存缓存 过期时间默认30s
     *
     * @param key
     * @param val
     */
    protected String setSession(String key, Object val) {
        return sessionService.setSession(key, val, getRequest());
    }

    /**
     * 保存缓存 过期时间默认30s
     *
     * @param key
     * @param val
     */
    protected String setSession(String key, Object val, long expire) {
        return sessionService.setSession(key, val, expire, getRequest());
    }

    /**
     * 删除缓存
     *
     * @param key
     */
    protected void delSession(String key) {
        sessionService.delSession(key, getRequest());
    }

    /**
     * 手机短信验证码验证
     */
    protected void checkUserPhoneCode(String mobile, String phoneCode, PhoneCodeKey codeKey) {
        if (StrUtil.isBlank(phoneCode)) {
            throw new BussinessException("短信验证码不能为空");
        }

        // 是否开通万能验证码
        Boolean superValidate = redisService.get(ConfigNID.SUPER_VALIDATE_OPEN, Boolean.class);
        if (superValidate != null && superValidate && "9999".equals(phoneCode)) {
            // 开通万能验证码，可使用万能验证码
            return;
        }
        String code = redisService.get(SessionId.MEMBER_MSG + codeKey.CACHE_ID + mobile);
        if (StrUtil.isBlank(code)) {
            throw new BussinessException("短信已过期,请重试");
        }
        if (!code.equals(phoneCode)) {
            throw new BussinessException("短信验证码错误");
        }
    }

    /**
     * 发送短信
     *
     * @param codeKey 短信模板对应枚举
     * @param mobile  手机号
     * @return 短信验证码
     * @throws Exception
     */
    protected String sendSmsCode(PhoneCodeKey codeKey, String mobile,Integer agentId) throws Exception {
        String cacheKey = SessionId.MEMBER_MSG + codeKey.CACHE_ID + mobile;
        // 判断是否已发送过验证码
        Date date = redisService.get(cacheKey + "_TIME", Date.class);
        if (date != null && DateUtil.between(date, new Date(), DateUnit.SECOND) < 60) {
            throw new BussinessException("请不要重复获取短信验证码");
        }
        MessageTemplate template = redisService.get(CacheID.TEMPLATE_MESSAGE_PREFIX + codeKey.nid, MessageTemplate.class);
        if (template == null) {
            throw new BussinessException("短信模板不存在");
        }
        // 是否开通短信通知
        Boolean openSms = redisService.get(ConfigNID.SMS_OPEN, Boolean.class);
        if (openSms) {
            String code = RandomUtil.randomNumbers(4);
            // 获取验证码有效期
            Integer limit = redisService.get(ConfigNID.VERIFY_CODE_TIME, Integer.class);
            Integer userId = 0;
            if (codeKey.isLogin) {
                User user = getLoginUser();
                if (user != null) {
                    userId = user.getId();
                }
            }
            // 内容参数
            HashMap<String, Object> params = new HashMap<>();
            params.put("code", code);
            params.put("limit", limit);
            sendMsgService.pushMessageQueue(codeKey.nid, params, template.getName(), userId, mobile, null,agentId);
            redisService.put(cacheKey, code, limit * 60);
            // 冗余短信重新发送时间
            redisService.put(cacheKey + "_TIME", new Date(), 60);
            return code;
        }
        throw new BussinessException("未开通短信通知");
    }

    /**
     * 获得登陆用户,未登陆/登录过期则return null
     *
     * @return 登陆user
     */
    protected User getLoginUser() {
        return getSession(SessionId.MEMBER_USER, User.class);
    }

    /**
     * 设置登陆用户
     *
     * @return 登陆user
     */
    protected void setLoginUser(User user) {
        setSession(SessionId.MEMBER_USER, user);
    }

    /**
     * 校验图片验证码
     *
     * @param captcha
     * @return
     */
    protected boolean checkCaptcha(String captcha) {
        String str = getSession(SessionId.CAPTCHA);
        // 是否开通万能验证码
        Boolean superValidate = redisService.get(ConfigNID.SUPER_VALIDATE_OPEN, Boolean.class);
        if (superValidate != null && superValidate && "9999".equals(captcha)) {
            // 开通万能验证码，可使用万能验证码
            return true;
        }
        if (StrUtil.isNotBlank(str) && StrUtil.isNotBlank(captcha) && StrUtil.equalsIgnoreCase(captcha, str)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 操作成功
     *
     * @return
     */
    protected <T> ResultEntity<T> ok() {
        return result(null, "success", ResultEntity.SUCCESS);
    }

    /**
     * 操作成功
     *
     * @param po 返回数据
     * @return
     */
    protected <T> ResultEntity<T> ok(String msg, T po) {
        return result(po, msg, ResultEntity.SUCCESS);
    }

    /**
     * 操作成功
     *
     * @param po 返回数据
     * @return
     */
    protected <T> ResultEntity<T> ok(T po) {
        return result(po, "success", ResultEntity.SUCCESS);
    }

    /**
     * 操作成功
     *
     * @param consumer 返回数据
     * @return
     */
    protected ResultEntity ok(Consumer<Map<String, Object>> consumer) {
        Map<String, Object> result = new HashMap<>();
        consumer.accept(result);
        return result(result, "success", ResultEntity.SUCCESS);
    }

    /**
     * 操作失败
     *
     * @return
     */
    protected <T> ResultEntity<T> fail(String msg) {
        return result(null, msg, ResultEntity.FAIL);
    }

    /**
     * 操作失败
     *
     * @return
     */
    protected <T> ResultEntity<T> fail() {
        return result(null, "fail", ResultEntity.FAIL);
    }

    /**
     * 返回消息记录
     *
     * @param resultData 返回实体(可空)
     * @param msg        返回消息
     * @param code       成功/错误
     * @return
     */
    protected <T> ResultEntity<T> result(T resultData, String msg, int code) {
        ResultEntity resultEntity = new ResultEntity();
        resultEntity.setData(resultData);
        resultEntity.setCode(code);
        resultEntity.setMessage(msg);
        return resultEntity;
    }

    /**
     * 继续请求
     *
     * @param resultData
     * @param msg
     * @param <T>
     * @return
     */
    protected <T> ResultEntity<T> loading(T resultData, String msg) {
        return result(resultData, msg, ResultEntity.LOADING);
    }

    /**
     * 继续请求
     *
     * @param <T>
     * @return
     */
    protected <T> ResultEntity<T> loading() {
        return loading(null, "loading");
    }

    protected HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    protected void checkRealNameStatus(User user) {
        if (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard())) {
            throw new BussinessException("请先实名认证");
        }
    }

    public String getRequestParams(HttpServletRequest request) {
        String params = "";
        try {
            request.setCharacterEncoding("UTF-8");
            InputStream in = request.getInputStream();
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            params = sb.toString();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return params;
    }

}
